package com.wallace.downloadserver.encrypt

import com.wallace.downloadserver.util.myEncrypt.AESCryptUtil
import org.junit.jupiter.api.Test
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.boot.test.context.SpringBootTest
import java.io.*
import java.util.*

@SpringBootTest
class StreamEncryptTest {

    private val log: Logger = LoggerFactory.getLogger(StreamEncryptTest::class.java)

    private val lineContent = "0123456789abcdefghijklmnopqrstuvwxyz~!@#$%^&*()-=_+<>0123456789abcdefghijklmnopqrstuvwxyz~!@#$%^&*()-=_+<>0123456789abcdefghijklmnopqrstuvwxyz~!@#$%^&*()-=_+<>\n"

    val filePath = "C:\\Users\\24959\\Desktop\\plain.txt"

    val aesKey = AESCryptUtil.generateKey()

    fun createFileBySpecifiedSize(fileSize: Long): File {
        log.debug("one line size = ${lineContent.length}")
        val file = File(filePath)
        if (!file.exists()) {
            file.createNewFile()
        }
        if (file.exists()) {
            var length = file.length()
            log.debug("current fileSize = $length")
            if (file.length() <= fileSize) {
                var row = 0
                val list = file.readLines()
                if (list.isNotEmpty()) {
                    val lines = list.last()
                    row = lines.split(".")[0].toInt()
                }
                log.debug("start at row = $row")
                while (file.length() < fileSize) {
                    row += 1
                    file.appendText("${row}.${lineContent}")
                    if (file.length() - length >= 10 * 1024 * 1024L) {
                        length = file.length()
                        log.debug("current fileSize = $length")
                    }
                }
                return file
            } else {
                file.writeText("")
                return createFileBySpecifiedSize(fileSize)
            }
        } else {
            throw FileNotFoundException("文件不存在")
        }
    }

    fun getInputStream(): InputStream? {
        val file = File(filePath)
        if (!file.exists()) {
            throw FileNotFoundException("文件不存在")
        } else {
            if (!file.isFile) {
                throw FileNotFoundException("非文件")
            } else {
                return file.inputStream()
            }
        }
    }

    @Test
    fun test() {
        val encoder = Base64.getEncoder()
        val decoder = Base64.getDecoder()
        createFileBySpecifiedSize(5 * 1024 * 1024L)
        // 加密
        val input = getInputStream()
        val buffer = ByteArray(8 * 1024)
        val file1 = File("C:\\Users\\24959\\Desktop\\plain_cipher.txt")
        input?.apply {
            if (file1.exists()) {
                log.debug("${file1.name} current size = ${file1.length()}")
                file1.delete()
            }
            if (!file1.exists()) {
                file1.createNewFile()
            }
            var length = this.read(buffer, 0, 8 * 1024)
            while (length > -1) {
                val plainByteArray = encoder.encode(buffer)
                val cipher = AESCryptUtil.encrypt(plainByteArray, aesKey.getSecretKeySpec(), aesKey.iv)
                if (cipher != null) {
                    file1.appendBytes(cipher)
                }
                length = this.read(buffer, 0, 8 * 1024)
            }
            log.debug("${file1.name} new size = ${file1.length()}")
        }

        // 解密
        val file2 = File("C:\\Users\\24959\\Desktop\\plain_cipher_plain.txt")
        if (file2.exists()) {
            log.debug("${file2.name} current size = ${file2.length()}")
            file2.delete()
        }
        if (!file2.exists()) {
            file2.createNewFile()
        }
        val input1 = file1.inputStream()
        input1.apply {
            val buffer1 = ByteArray(8 * 1024)
            var length = this.read(buffer, 0, 8 * 1024)
            while (length > -1) {
                val plainByteArray = AESCryptUtil.decrypt(buffer1, aesKey.getSecretKeySpec(), aesKey.iv)
                if (plainByteArray != null) {
                    val plain = decoder.decode(plainByteArray)
                    file2.appendBytes(plain)
                }
                length = this.read(buffer, 0, 8 * 1024)
            }
            log.debug("${file2.name} new size = ${file2.length()}")
        }
    }
}